Skip to content

v2.9.0 - rebrand and native app prep - #265

Merged
TheAngryRaven merged 46 commits into
mainfrom
BETA
Jun 22, 2026
Merged

v2.9.0 - rebrand and native app prep#265
TheAngryRaven merged 46 commits into
mainfrom
BETA

Conversation

@TheAngryRaven

@TheAngryRaven TheAngryRaven commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Promotes BETA → main as v2.9.0. Everything since 2.8.0, grouped by theme. Coach ships on the published npm package (@perchwerks/eye-in-the-sky@0.5.0) — release config.

🎨 Rebrand → LapWing

  • Renamed HackTheTrack → LapWing; brand accent moved teal → purple, with a new LapWing logo (shared BrandLogo), refreshed app icons + favicon.
  • Wired up lapwingdata.com (+ beta.lapwingdata.com proxy).
  • Tapping the header logo in an open session returns to the home screen.

📱 Native Android app prep (Tauri)

  • Same frontend serves a native Android shell; isNativeApp() gates native-only behavior.
  • Safe-area insets across every full-screen surface (status bar / notch).
  • Paid-plan UI hidden on native (Google Play billing policy) — registration shows only the free sign-up; profile billing buttons hidden. Cloud sync still works.
  • External links open in the system browser on native (Tauri opener plugin / __HTT_NATIVE__ bridge), not the in-app WebView.
  • Leaner native landing (hero, roadmap, GitHub/sponsor links hidden).
  • Public /delete-account page.

🔌 Loggers & downloads

  • Generic LoggerConnection layer (listLogs/downloadLog/disconnect) — one seam for all transports.
  • Logger picker — image-based chooser (Fledgling / MyChron / Alfano); eager-loaded so it opens instantly; mobile-friendly (compact cards, height cap, close button, safe-area padding); real product photos; trademark/ownership note.
  • Download from a MyChron over Wi-Fi (native app) via createMychronConnection(); Android system Wi-Fi picker; native-only Settings → MyChron SSID-prefix field. @tauri-apps/api is lazy-loaded (off the web bundle).
  • Device tab is Fledgling-gated (settings/tracks/firmware).
  • "Download from DovesDataLogger" → "Download from logger"; landing upload is now a 50/50 dropzone + logger split.

🖥️ Landing & auth/legal UI

  • Sticky landing banner (login always reachable; clean under the mobile status bar).
  • Shared, sticky, clickable BrandHeader (→ home) on login / register / privacy / terms; privacy/terms gain mobile safe-area padding.
  • Open-source GitHub links moved into the About dialog (under "Free & Open Source"); About feature list refreshed (7 languages, native MyChron download, phone-as-logger, cloud sync, AI coach).
  • Footer/link cleanup; Privacy/Terms links on the sign-in page; "Back to app" returns to where you came from.

☁️ Accounts & cloud

  • Password strength rules + realtime offline checker on sign-up.
  • Separate cloud + local storage bars in the profile.
  • "Update available" check independent of the service worker (build-emitted version.json).

🐛 Fixes

  • External links no longer open inside the native app.
  • Login rate limiter no longer locks out valid sign-ins (counts only genuine failures, 15-min sliding window).

Full detail in CHANGELOG.md under [2.9.0]. Depends on #281 (release cut + About move) landing in BETA first.

🤖 Generated with Claude Code

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Jun 21, 2026

Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Preview URL Updated (UTC)
✅ Deployment successful!
View logs
lapwing e00c53a Commit Preview URL

Branch Preview URL
Jun 22 2026, 03:10 AM

@supabase

supabase Bot commented Jun 21, 2026

Copy link
Copy Markdown

This pull request has been ignored for the connected project tdxloldxzvnzdivdazzd because there are no changes detected in supabase directory. You can change this behaviour in Project Integrations Settings ↗︎.


Preview Branches by Supabase.
Learn more about Supabase Branching ↗︎.

@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown

Coverage Summary

Lines: 58.96% (6011/10195) · Statements: 58.04% · Functions: 56.37% · Branches: 54.04%

Per-file coverage
File Lines Functions Branches
src/components/map/positionArrowMarker.ts 0% 0% 0%
src/components/video-overlays/dataSourceResolver.ts 85.07% 71.42% 80.82%
src/components/video-overlays/overlayUtils.ts 100% 100% 100%
src/components/video-overlays/registry.ts 100% 100% 100%
src/components/video-overlays/sectorUtils.ts 94.73% 100% 84.37%
src/components/video-overlays/themes.ts 100% 100% 100%
src/components/video-overlays/types.ts 100% 100% 100%
src/hooks/use-mobile.tsx 0% 0% 100%
src/hooks/use-toast.ts 0% 0% 0%
src/hooks/useAuth.ts 100% 100% 100%
src/hooks/useDataLoader.ts 14.11% 20% 17.02%
src/hooks/useDocumentHead.ts 0% 0% 0%
src/hooks/useEngineManager.ts 0% 0% 0%
src/hooks/useFileManager.ts 0% 0% 0%
src/hooks/useFirmwareUpdate.ts 0% 0% 0%
src/hooks/useKartManager.ts 100% 100% 100%
src/hooks/useLapManagement.ts 0% 0% 0%
src/hooks/useLapOverlays.ts 0% 0% 0%
src/hooks/useLapSnapshots.ts 0% 0% 0%
src/hooks/useNoteManager.ts 0% 0% 0%
src/hooks/useOnlineStatus.ts 0% 0% 0%
src/hooks/usePlayback.ts 0% 0% 0%
src/hooks/useReferenceLap.ts 0% 0% 0%
src/hooks/useSessionData.ts 0% 0% 0%
src/hooks/useSessionMetadata.ts 0% 0% 0%
src/hooks/useSettings.ts 0% 0% 0%
src/hooks/useSetupManager.ts 0% 0% 100%
src/hooks/useStripePrices.ts 0% 0% 0%
src/hooks/useSubscription.ts 0% 0% 0%
src/hooks/useTemplateFields.ts 0% 0% 0%
src/hooks/useTemplateManager.ts 0% 0% 0%
src/hooks/useTrackEditorForm.ts 0% 0% 0%
src/hooks/useVehicleManager.ts 0% 0% 100%
src/hooks/useVideoSync.ts 0% 0% 0%
src/hooks/useWakeLock.ts 0% 0% 0%
src/hooks/useWaybackImagery.ts 0% 0% 0%
src/integrations/lovable/index.ts 0% 0% 0%
src/lib/test/idb.ts 100% 100% 100%
src/lib/aimParser.ts 95.85% 100% 81.46%
src/lib/alfanoParser.ts 83.22% 100% 61.9%
src/lib/billing.ts 97.36% 100% 98.21%
src/lib/billingClient.ts 0% 0% 0%
src/lib/ble/test/mockBle.ts 96% 90% 50%
src/lib/ble/battery.ts 93.33% 100% 87.5%
src/lib/ble/connection.ts 0% 0% 0%
src/lib/ble/dfu/dfuPackage.ts 96.66% 100% 71.87%
src/lib/ble/dfu/dfuTypes.ts 100% 100% 100%
src/lib/ble/dfu/firmwareManifest.ts 96.92% 92.85% 93.18%
src/lib/ble/dfu/index.ts 100% 100% 100%
src/lib/ble/dfu/version.ts 96.77% 100% 83.33%
src/lib/ble/fileTransfer.ts 90.69% 95% 72.91%
src/lib/ble/firmwareCrc.ts 100% 100% 100%
src/lib/ble/firmwareUpload.ts 90.4% 87.5% 84.31%
src/lib/ble/format.ts 100% 100% 100%
src/lib/ble/index.ts 100% 100% 100%
src/lib/ble/internal.ts 100% 100% 50%
src/lib/ble/settings.ts 93.6% 100% 85.29%
src/lib/ble/trackSync.ts 89.69% 90.9% 70.96%
src/lib/ble/types.ts 100% 100% 100%
src/lib/bleDatalogger.ts 100% 100% 100%
src/lib/brakingZones.ts 97.14% 100% 86.11%
src/lib/browserCompat.ts 0% 0% 0%
src/lib/buildInfo.ts 100% 100% 100%
src/lib/canvas2d.ts 100% 100% 91.66%
src/lib/channels.ts 100% 100% 84.61%
src/lib/chartAxis.ts 98% 100% 82.92%
src/lib/chartColors.ts 100% 100% 100%
src/lib/chartUtils.ts 100% 100% 97.05%
src/lib/courseDetection.ts 97.16% 100% 80.23%
src/lib/courseSectors.ts 100% 100% 94.87%
src/lib/datalogParser.ts 83.56% 80% 81.81%
src/lib/db/index.ts 0% 0% 0%
src/lib/db/supabaseAdapter.ts 0% 0% 0%
src/lib/db/types.ts 100% 100% 100%
src/lib/dbUtils.ts 76.23% 80% 17.2%
src/lib/debugConsole.ts 57.74% 61.11% 47.72%
src/lib/deviceSettingsSchema.ts 93.33% 100% 96.42%
src/lib/deviceTrackSync.ts 100% 100% 100%
src/lib/doveParser.ts 89.6% 72.72% 77.27%
src/lib/dovexParser.ts 90.62% 100% 80%
src/lib/emailValidation.ts 100% 100% 100%
src/lib/engineStorage.ts 100% 75% 100%
src/lib/engineUtils.ts 100% 100% 91.66%
src/lib/fieldResolver.ts 100% 100% 83.33%
src/lib/fileBrowserTree.ts 98.87% 97.5% 89.36%
src/lib/fileLoadingState.ts 100% 100% 100%
src/lib/fileStorage.ts 82.79% 78.12% 72.22%
src/lib/garageEvents.ts 100% 100% 100%
src/lib/gforceCalculation.ts 100% 100% 97.22%
src/lib/ggDiagram.ts 100% 100% 94.73%
src/lib/gps/customGps.ts 100% 100% 82.05%
src/lib/gps/dovepWriter.ts 100% 100% 92%
src/lib/gps/gpsFix.ts 100% 100% 100%
src/lib/gps/index.ts 100% 100% 100%
src/lib/gps/observationSample.ts 100% 100% 100%
src/lib/gps/realtimeTimer.ts 90.07% 100% 76.04%
src/lib/gps/sessionGate.ts 100% 100% 100%
src/lib/graphPrefsStorage.ts 100% 100% 100%
src/lib/i18n/config.ts 100% 100% 100%
src/lib/i18n/format.ts 100% 100% 85.71%
src/lib/i18n/pluginLocales.ts 0% 0% 100%
src/lib/i18n/seedUtils.ts 100% 100% 90.47%
src/lib/iracingParser.ts 91.93% 80% 76.47%
src/lib/kartStorage.ts 100% 75% 100%
src/lib/lapAlignment.ts 100% 80% 76.92%
src/lib/lapCalculation.ts 96.31% 100% 90.9%
src/lib/lapDelta.ts 99.2% 100% 85.07%
src/lib/lapOverlays.ts 100% 100% 86%
src/lib/lapSnapshot.ts 100% 100% 88.46%
src/lib/lapSnapshotStorage.ts 100% 83.33% 100%
src/lib/logFileType.ts 100% 100% 100%
src/lib/loggers/fledglingConnection.ts 100% 100% 100%
src/lib/loggers/index.ts 100% 100% 100%
src/lib/loggers/mychron/ipc.ts 89.47% 83.33% 100%
src/lib/loggers/mychron/mychronConnection.ts 100% 100% 100%
src/lib/loggers/progress.ts 94.73% 100% 96.15%
src/lib/loggers/types.ts 100% 100% 100%
src/lib/mapMarker.ts 100% 100% 100%
src/lib/motecParser.ts 89.61% 81.48% 55.71%
src/lib/navBack.ts 100% 100% 71.42%
src/lib/nmeaParser.ts 85.62% 92.85% 71.22%
src/lib/noteStorage.ts 100% 80% 100%
src/lib/overlayCanvasRenderer.ts 0% 0% 0%
src/lib/parserUtils.ts 100% 100% 98.52%
src/lib/passwordStrength.ts 100% 100% 100%
src/lib/pendingCheckout.ts 58.82% 25% 100%
src/lib/platform.ts 100% 87.5% 91.3%
src/lib/profanity.ts 100% 100% 75%
src/lib/referenceUtils.ts 100% 100% 91.11%
src/lib/sampleData.ts 100% 100% 100%
src/lib/satelliteImagery.ts 100% 100% 90%
src/lib/setupHistory.ts 94.17% 100% 72.51%
src/lib/setupRevision.ts 100% 100% 94.11%
src/lib/setupRevisionStorage.ts 84.48% 78.26% 36.84%
src/lib/setupStatus.ts 100% 100% 100%
src/lib/setupStorage.ts 81.35% 58.62% 100%
src/lib/speedBounds.ts 94.28% 66.66% 87.17%
src/lib/speedEvents.ts 86.56% 100% 76%
src/lib/speedHeatmap.ts 100% 100% 100%
src/lib/submittedTracksStorage.ts 0% 0% 0%
src/lib/templateEdit.ts 97.82% 88.88% 86.95%
src/lib/templateStorage.ts 93.54% 69.23% 100%
src/lib/trackStorage.ts 16.4% 28.3% 18.18%
src/lib/trackSubmission.ts 100% 100% 95.91%
src/lib/trackUtils.ts 100% 100% 97.05%
src/lib/ubxParser.ts 99% 100% 89.58%
src/lib/units.ts 100% 100% 100%
src/lib/utils.ts 100% 100% 100%
src/lib/vboParser.ts 90.66% 100% 71.59%
src/lib/vehicleHistory.ts 97.29% 100% 80%
src/lib/vehicleStorage.ts 100% 75% 100%
src/lib/versionCheck.ts 19.44% 12.5% 44.73%
src/lib/videoExport.ts 0% 0% 0%
src/lib/videoExportTarget.ts 100% 100% 84.61%
src/lib/videoFileStorage.ts 100% 76% 61.11%
src/lib/videoPlaylist.ts 95.71% 100% 90%
src/lib/videoStorage.ts 100% 76.92% 77.77%
src/lib/wakeLock.ts 100% 80% 100%
src/lib/weatherCacheStorage.ts 100% 100% 100%
src/lib/weatherService.ts 23.8% 35.29% 25.89%
src/lib/xrk/xrkClient.ts 3.57% 0% 0%
src/lib/xrk/xrkConfig.ts 100% 100% 100%
src/lib/xrk/xrkImporter.ts 70% 75% 80%
src/lib/xrk/xrkMapping.ts 98.7% 100% 82.81%
src/lib/xrk/xrkResample.ts 100% 100% 90.9%
src/lib/xrk/xrkTypes.ts 100% 100% 100%
src/lib/xrk/xrkWorker.ts 0% 0% 0%
src/plugins/cloud-sync/accountDeletion.ts 100% 100% 100%
src/plugins/cloud-sync/accountExport.ts 0% 0% 0%
src/plugins/cloud-sync/accountImport.ts 13.51% 25% 26.08%
src/plugins/cloud-sync/activeUser.ts 100% 100% 100%
src/plugins/cloud-sync/autoSync.ts 0% 0% 0%
src/plugins/cloud-sync/cloudClient.ts 69.23% 42.85% 87.5%
src/plugins/cloud-sync/CloudLogsPanel.tsx 0% 0% 0%
src/plugins/cloud-sync/DataPrivacyPanel.tsx 0% 0% 0%
src/plugins/cloud-sync/exportManifest.ts 100% 100% 100%
src/plugins/cloud-sync/FileDeleteToggle.tsx 0% 0% 0%
src/plugins/cloud-sync/fileSync.ts 100% 100% 100%
src/plugins/cloud-sync/FileSyncToggle.tsx 0% 0% 0%
src/plugins/cloud-sync/index.ts 0% 0% 0%
src/plugins/cloud-sync/LapSnapshotsPanel.tsx 0% 0% 0%
src/plugins/cloud-sync/localUsage.ts 100% 100% 50%
src/plugins/cloud-sync/merge.ts 100% 100% 100%
src/plugins/cloud-sync/pendingSync.ts 100% 100% 100%
src/plugins/cloud-sync/profile.ts 100% 100% 100%
src/plugins/cloud-sync/setupRevisionTombstones.ts 100% 100% 83.33%
src/plugins/cloud-sync/snapshotSync.ts 97.22% 87.5% 75%
src/plugins/cloud-sync/snapshotTombstones.ts 100% 100% 100%
src/plugins/cloud-sync/StoragePanel.tsx 0% 0% 0%
src/plugins/cloud-sync/storageTypes.ts 100% 100% 100%
src/plugins/cloud-sync/storeAccessors.ts 100% 100% 90%
src/plugins/cloud-sync/syncEngine.ts 98.9% 95% 80%
src/plugins/cloud-sync/syncStores.ts 100% 100% 100%
src/plugins/fileSources.ts 0% 0% 100%
src/plugins/index.ts 0% 0% 0%
src/plugins/mounts.ts 71.42% 75% 100%
src/plugins/panels.ts 75% 83.33% 100%
src/plugins/PluginMount.tsx 0% 0% 0%
src/plugins/PluginPanelHost.tsx 0% 0% 0%
src/plugins/registry.ts 77.27% 50% 100%
src/plugins/storage.ts 90.32% 70.83% 66.66%
src/plugins/tools/i18n.ts 0% 0% 100%
src/plugins/tools/index.ts 0% 0% 100%
src/plugins/tools/laptimer/lapTimerSession.ts 89.06% 80% 84.37%
src/plugins/tools/laptimer/LapTimerTool.tsx 0% 0% 0%
src/plugins/tools/laptimer/useLapTimer.ts 0% 0% 0%
src/plugins/tools/seat-position/model.ts 100% 100% 60%
src/plugins/tools/seat-position/SeatDiagram.tsx 0% 0% 0%
src/plugins/tools/seat-position/SeatPositionTool.tsx 0% 0% 0%
src/plugins/tools/toolList.ts 0% 0% 100%
src/plugins/tools/ToolsLandingTile.tsx 0% 0% 0%
src/plugins/tools/ToolsPanel.tsx 0% 0% 0%
src/plugins/types.ts 100% 100% 100%
src/types/racing.ts 0% 0% 0%

claude and others added 24 commits June 21, 2026 04:08
Recolor the brand accent from teal to purple (#8746b3 = HSL 276 44% 49%): set
--primary and its mirrors (--ring, --sidebar-primary, --sidebar-ring) in both
light and dark (keeping the existing light/dark lightness split). Data-viz
tokens (speed/telemetry scales) are untouched.

Replace the gauge glyph in the app/page headers (Landing, Index, Login,
Register, Forgot/Reset password, Admin) with the new web-logo.png via a small
shared BrandLogo component. Functional gauge icons (weather pressure, g-force
setting, garage tab, coach, analog-gauge overlay) are left as-is.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WyjporYvTUjrP2a29wKKPo
Two mobile/native polish fixes:

- Tapping the LapWing logo (top-left) in an open session now closes the
  session and returns to the landing page, via a new `clearSession` on
  useSessionData. Added a `header.home` aria-label (seeded to all locales).
- App shell now respects device safe-area insets so header content no longer
  sits under the status bar / notch on native and installed PWAs. Added
  `viewport-fit=cover` and a reusable `.safe-area-inset` utility applied to
  the session + landing shells (border-box keeps padding inside the full-height
  containers; a no-op where there's no safe area).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PpQppp3sdsZXLRUGf1F69g
…rmwrb

Mobile UI cleanup: logo → home + safe-area insets
Replace the direct Bluetooth jump behind "Download from logger" with an
image-based chooser of supported loggers:

- PerchWerks Fledgling (DIY, Bluetooth) -> runs the existing BLE download
- AiM MyChron 5/5S/2T (Wi-Fi, native app required) -> explanatory dialog;
  copy differs on the native shell (placeholder "TBD") vs the web app
  (native app in development, ~July 2026)
- Alfano 6/7 (Bluetooth, coming soon) -> explanatory dialog (~early July '26)

Also relabels the file-manager "Download from DovesDataLogger" button to
"Download from logger". New `logger` i18n namespace (all 7 locales) and
placeholder artwork under public/loggers/ for easy swap-out.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HLRuG1p8vhUXFP5V34WVET
…u-erwc9f

Image-based logger picker for "Download from logger"
Three changes building on the logger picker:

1. Fix the home-screen "Download from logger" button. The picker was buried
   inside the lazy BLE chunk, so on the landing it sat behind a disabled
   Suspense fallback and clicks did nothing when that chunk stalled. Split the
   lightweight picker into an eager host (LoggerDownload); the heavy Fledgling
   BLE flow is mounted on demand once the Fledgling is picked, so the menu opens
   instantly while lib/ble/* stays off the initial payload.

2. Generic logger-connection layer (src/lib/loggers/). The download UI talks to
   every logger through one LoggerConnection interface (listLogs / downloadLog /
   disconnect); createFledglingConnection() adapts the BLE transport. This is the
   seam MyChron (native/Tauri) and Alfano will plug into. DeviceContext now tracks
   the connected loggerKind.

3. Device tab is Fledgling-gated: shows a "Fledgling only" notice when the
   connected logger isn't a Fledgling (groundwork for non-Fledgling connections,
   which have no settings/tracks/firmware surface).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HLRuG1p8vhUXFP5V34WVET
…u-erwc9f

Fix home download button + generic logger-connection layer
The login screen now links to the Privacy Policy and Terms of Service,
reusing the existing landing-namespace link labels (no new keys).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQYR6dBauo2iSyqt8VkyU
Restyle the Credits dialog trigger to match the Browser Compatibility
button so the two read as a matched pair when placed side by side.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQYR6dBauo2iSyqt8VkyU
- Primary action is now a 50/50 split: an equal-billing "Download from
  logger" panel beside the drag-and-drop dropzone (most users pull logs
  straight off a logger). The separate logger ActionTile is removed.
- Native (Tauri/Android) shell hides marketing surfaces it doesn't need:
  the hero pitch, the feature roadmap, the GitHub repo links and the
  sponsor button. The DIY "Build your own logger" tile stays.
- Move Privacy/Terms out of the mid-page row: on the stable build they
  now flank the operated-by/version block in the footer. Credits moves up
  next to the Browser Compatibility button.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQYR6dBauo2iSyqt8VkyU
The Privacy and Terms pages hardcoded their back link to the home route,
so opening Terms/Privacy from the sign-in or register screen and clicking
back dumped the user on the landing page. Use a small goBackOrHome helper
that steps back one history entry when there's an in-app page to return
to, falling back to home only when the page was opened directly (fresh
tab, bookmark, external link).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQYR6dBauo2iSyqt8VkyU
…native-hf5ydp

UI cleanup: landing page split, leaner native shell, footer/login link tidy-up
Add docs/ble-protocol.md: a transport-agnostic specification of the full
BLE connection stack (GATT services/characteristics, every command and
response packet across file/battery/settings/track/firmware protocols, DIS
version read, and a native-port checklist) so the connection can be
replicated in any stack — e.g. the Tauri shell — without reading the
TypeScript reference client.

Cross-reference it from docs/ble.md and add a CLAUDE.md pointer plus a
keep-in-sync rule so future wire-format changes update the spec.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016C8usikqirgjsfH7djYt8Q
When signed in the profile now renders two storage meters — cloud quota
and on-device local — instead of only the cloud one. The local bar gets
an (i) tooltip (click or hover; works on touch) explaining that the
device's real free space isn't exposed to the app, so the bar is drawn
against an arbitrary 10 GB advisory marker and can be ignored — local
storage has no limit.

- localUsage now uses a fixed LOCAL_ADVISORY_LIMIT (10 GB) instead of the
  browser's storage estimate, matching what the tooltip tells the user.
- The cloud and local meters refresh independently so the local one stays
  accurate offline (no network) and updates live on on-device changes.
- The "sign in to back it up" footnote is suppressed on the signed-in
  local bar, where it would be both redundant and wrong.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQYR6dBauo2iSyqt8VkyU
…umentation-fps9eq

Document the DovesDataLogger BLE protocol as a portable wire spec
beta-proxy/ (the beta.lapwingdata.com reverse proxy) is a separate Worker
from the main app, which Cloudflare's connected-repo CI builds — nothing
was deploying the proxy, so it had to be pushed by hand.

Add deploy-beta-proxy.yml: deploy on BETA pushes that touch beta-proxy/**
(and on demand via workflow_dispatch) using cloudflare/wrangler-action,
and dry-run validate it on PRs (no secrets, so fork PRs work too). The
wrangler version is pinned for reproducible runs since beta-proxy has no
committed lockfile.

Deploy needs two repo secrets: CLOUDFLARE_API_TOKEN (Edit Workers) and
CLOUDFLARE_ACCOUNT_ID. Documented in beta-proxy/README.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQYR6dBauo2iSyqt8VkyU
…s-local

Profile: separate cloud + local storage bars with a local-limit tooltip
The limiter called check-login-rate before the login and incremented the
IP's counter on EVERY attempt — successes included — so five tries (even
correct ones) locked the IP for an hour. It also never reset on success
and sub-threshold failures never aged out.

Rework it around what actually happened:
- pre-login "check" only reports lock state, never mutates;
- a failure is recorded only when the password was actually wrong;
- a success clears the IP's counter;
- failures accumulate over a 15-minute sliding window (new updated_at
  column + shared trigger) so old stray failures don't pile up.

The decision logic is extracted to a pure rateLimit.ts shared by the
edge function and a Vitest regression test (vitest now also picks up
supabase/functions pure-logic tests; coverage stays src/-only).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01TcQYR6dBauo2iSyqt8VkyU
Fix login rate limiter locking out valid sign-ins
The PWA's only update path was the service worker noticing a byte-diff in
its own file (registration.update() every 60s -> onNeedRefresh toast). That
can silently stall behind HTTP/CDN caching, leaving a tab pinned to a stale
build with no prompt.

Add an independent freshness signal: vite emits a tiny /version.json next to
the bundle from the same build constants as buildInfo, excluded from the
Workbox precache. versionCheck.ts fetches it uncached (on start, on an
interval, and on focus/reconnect) and compares against the running build;
when a genuinely newer deploy is live it surfaces the existing "Update ready"
toast. The toast is now shared/deduped between the SW callback and the poller,
and its Refresh hard-reboots (updateSW(true) with an unregister+reload
fallback for the stale-SW case).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01R2ErrGGyzGeQDyq6hwdRYU
…-qxj01o

Add deploy-version check independent of the service worker
Registration accepted any 6+ character password with no feedback. Add an
offline password-strength evaluator (lib/passwordStrength.ts) that enforces
length plus character-class rules, and a PasswordStrengthMeter component that
shows a live strength bar and per-rule checklist as the user types. Block
sign-up until every rule passes, and translate the new strings across all
shipped locales.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Rs8GJ1Wsy1izavKFUDvFSM
…rd-security-7q2w7k

Add password rules + realtime strength checker to sign-up
@TheAngryRaven TheAngryRaven changed the title v2.9.0 - quick rebrand v2.9.0 - rebrand and native app prep Jun 21, 2026
claude and others added 14 commits June 21, 2026 22:41
The safe-area-inset utility was only applied to the main app shell and
landing page, leaving other full-screen surfaces drawing edge-to-edge on
native/installed-PWA. Their top chrome sat under the device status bar:

- File-manager drawer: its garage/profile/device header (title, battery,
  disconnect, close) is a portal overlay outside the padded app shell.
- Full-page routes: login, register, admin, privacy, terms, delete-account,
  404 — each owns its own min-h-screen root.

Apply the existing reusable .safe-area-inset utility to all of them. No-op
on browsers/desktops without a safe area (insets resolve to 0).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FojvNNtPyxoixHn2mR5Txu
Wires the MyChron tile in the logger picker to a real native-only download
flow, mirroring the existing BLE (Fledgling) downloader. Single-download scope.

- mychron/ipc.ts: typed Tauri IPC client (logger_connect/list/download/disconnect)
  reaching @tauri-apps/api via a dynamic import so it code-splits out of the web
  bundle entirely (web build never fetches Tauri).
- createMychronConnection(): second LoggerConnection adapter (native, Wi-Fi).
- MyChronDownload.tsx: lazy UI mirroring the BLE flow's panels + a Wi-Fi
  "pick your MyChron" state; imports via the async XRK path (parseDatalogFile)
  since the device returns binary XRK bytes; owns and always tears down its
  connection.
- Shared file-list/progress panels extracted to components/loggers; pure progress
  formatters + computeProgress moved to transport-neutral lib/loggers/progress.ts
  (ble/format.ts re-exports them).
- Picker/host wiring, logger i18n keys, docs, Credits, and changelog updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbxsCSt8grPs75vfJyt8wP
…dding-7k3868

Extend safe-area insets to drawer + full-page routes
Replaces the English fallback for the mychron.flow.* keys with proper
translations in es/fr/de/it/pt-BR/ja, reusing established terms (Browse
Files, Cancel, Retry, Connecting) for consistency. German uses WLAN; the
rest keep Wi-Fi.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbxsCSt8grPs75vfJyt8wP
Adds a native-only Settings → MyChron text field for the Wi-Fi name prefix
the Android system picker filters on, so a logger that broadcasts a different
name can still be found. Persists via useSettings (localStorage), defaults to
"MYCHRON5" (mirrors MYCHRON_SSID_PREFIX), and is read in MyChronDownload with
the constant as fallback. Field is gated on isNativeApp(). Translated in all
six locales; docs + changelog updated.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbxsCSt8grPs75vfJyt8wP
…v5nu

Make MyChron Wi-Fi SSID prefix configurable in Settings
- Sticky landing banner: the landing header is now pinned to the top (login
  button always visible; content scrolls cleanly under the status bar on
  mobile). Top safe-area inset moves onto the sticky header.
- Shared BrandHeader: extract the logo+name header into one sticky, clickable
  (→ home) component, reused on login/register/privacy/terms. Privacy/terms now
  also carry safe-area padding via the shared header.
- Native: hide the entire pricing-cards section on the registration page (only
  the free sign-up form shows). Profile billing buttons were already gated.
- External links open in the system browser on native (Tauri): openExternal now
  routes through @tauri-apps/plugin-opener when the __HTT_NATIVE__ bridge isn't
  wired, instead of navigating the in-app WebView. Dynamically imported so it
  stays out of the web bundle.
- Add safe-area-x / safe-area-top CSS utilities for the sticky-header layout.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbxsCSt8grPs75vfJyt8wP
- Swap the placeholder SVGs for the real MyChron/Alfano/Fledgling product
  photos (public/loggers/*.png).
- Mobile: compact horizontal cards (image thumbnail + text) instead of
  full-height image cards that filled the screen; from sm+ the full image
  card layout is unchanged.
- Cap the dialog height with internal scroll + native safe-area padding so a
  tall list never pushes the close (X) above the top of the screen on mobile.
- Add an explicit Close button on mobile (desktop keeps the corner X).
- Add a trademark/ownership note for the MyChron and Alfano brands (translated
  across all locales).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbxsCSt8grPs75vfJyt8wP
The earlier safe-area-inset on the picker dialog set padding to a bare env()
inset, which collapses to 0 on un-notched devices and overrode the dialog's
default p-6 — scrunching the content against the panel border. Replace it with
a safe-area-modal utility (max(1.5rem, env()) on every side) so padding never
drops below the base while still clearing notches, and add a w-[calc(100%-2rem)]
side gutter so the panel isn't edge-to-edge on mobile.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbxsCSt8grPs75vfJyt8wP
MyChron download only works in the native app, which isn't public yet, so show
a "Coming soon" badge to web users (matching Alfano). On native it works, so no
badge there.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbxsCSt8grPs75vfJyt8wP
…weaks

Landing/auth UI polish + native gating tweaks
…ture list

- Cut the unreleased changelog section as 2.9.0 and bump package.json to 2.9.0.
  Coach stays on the published npm package (@perchwerks/eye-in-the-sky@0.5.0) —
  BETA has been on it since the 2.7.0 cut (never flipped back to the git dep), so
  it's already in release config; no flip needed for the main push.
- Move the open-source GitHub repo links off the landing page and into the About
  dialog, under the "Free & Open Source" section, above the feature list. Shown on
  all platforms there (consistent with Credits), so the native landing stays lean.
- Refresh the About feature list with the headline additions from the last month
  (7 languages, native Android app + MyChron Wi-Fi download, phone-as-logger GPS
  timing, optional cloud sync, AI coach), translated across all locales.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbxsCSt8grPs75vfJyt8wP
claude and others added 4 commits June 22, 2026 02:57
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbxsCSt8grPs75vfJyt8wP
Release 2.9.0: About-dialog GitHub links + feature refresh + version cut
- Shorten logger names to "AiM MyChron 5+" and "Alfano 6+" so they fit on one
  line and don't pin to specific models (the protocol may cover newer ones).
- Add the shared sticky BrandHeader to the account-deletion page.
- Remove the "Telemetry Data Viewer" tagline from the landing header for now
  (locale keys kept for a future replacement).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AbxsCSt8grPs75vfJyt8wP
Picker name tidy, delete-account header, drop landing tagline
@TheAngryRaven
TheAngryRaven marked this pull request as ready for review June 22, 2026 03:11
@TheAngryRaven
TheAngryRaven merged commit 3c60ceb into main Jun 22, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants